/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hudson.msservice.messageservice;

/**
 *
 * @author janksenhu
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.MessageFormat;
import java.util.List;
import org.apache.commons.codec.binary.Base64;
import org.apache.log4j.Logger;

/**
 * @author janksenhu
 */
public class MessageServiceProxy {

    /**
     *
     *
     * @author janksenhu
     */
    static Logger logger = Logger.getLogger("接口");
    public static final String MSG_PRIORITY_HIGHT = "Hight";
    public static final String MSG_PRIORITY_NORMAL = "Normal";
    public static final String MSG_PRIORITY_LOW = "Low";
    public static final String MSG_MAIL_BODYFORMAT_TEXT = "Text";
    public static final String MSG_MAIL_BODYFORMAT_HTML = "Html";
    public static final String MSG_MAIL_TYPE_INTERNET = "SEND_TO_INTERNET";
    public static final String MSG_MAIL_TYPE_ENCHANGE = "SEND_TO_ENCHANGE";
    public static final String MSG_MAIL_TYPE_MEETING = "SEND_TO_MEETING";
    public static final String APP_KEY_DEFAULT = "96bba6d1c19d480a8a2cdb7f4f7d8f22";
    public static final String SEND_TYPE_RTX = "SendRTX";
    public static final String SEND_TYPE_SMS = "SendSMS";
    public static final String SEND_TYPE_EMAIL = "SendMail";
    private static MessageServiceProxy instance = new MessageServiceProxy();
    /**
     *
     */
    static final String SOAP_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> "
            + "<SOAP-ENV:Envelope "
            + "xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" "
            + "xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" "
            + "xmlns:xsd=\"http://www.w3.org/1999/XMLSchema\" "
            + "xmlns:xsi=\"http://www.w3.org/1999/XMLSchema-instance\" "
            + "SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" > "
            + "<SOAP-ENV:Header> "
            + "<Application_Context xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\"> "
            + "<AppKey xmlns=\"http://schemas.datacontract.org/2004/07/Tencent.OA.Framework.Context\">"
            + APP_KEY_DEFAULT
            + "</AppKey> "
            + "</Application_Context> "
            + "</SOAP-ENV:Header> ";
    static String SOAP_BODY_TEMPLATE_RTX = "<SOAP-ENV:Body> "
            + "<n2:SendRTX xmlns:n2=\"http://tempuri.org/\"> "
            + "<n2:message xmlns:n3=\"http://schemas.datacontract.org/2004/07/Tencent.OA.Framework.Messages.DataContract\"> "
            + "<n3:MsgInfo><![CDATA[{0}]]></n3:MsgInfo> "
            + "<n3:Priority>{1}</n3:Priority> "
            + "<n3:Receiver>{2}</n3:Receiver> "
            + "<n3:Sender>{3}</n3:Sender> "
            + "<n3:Title><![CDATA[{4}]]></n3:Title> "
            + "</n2:message> "
            + "</n2:SendRTX> "
            + "</SOAP-ENV:Body> "
            + "</SOAP-ENV:Envelope>";
    static final String SOAP_BODY_TEMPLATE_SMS = "<SOAP-ENV:Body> "
            + "<n2:SendSMS xmlns:n2=\"http://tempuri.org/\"> "
            + "<n2:message xmlns:n3=\"http://schemas.datacontract.org/2004/07/Tencent.OA.Framework.Messages.DataContract\"> "
            + "<n3:MsgInfo><![CDATA[{0}]]></n3:MsgInfo> "
            + "<n3:Priority>{1}</n3:Priority> "
            + "<n3:Receiver><![CDATA[{2}]]></n3:Receiver> "
            + "<n3:Sender><![CDATA[{3}]]></n3:Sender> "
            + "</n2:message> "
            + "</n2:SendSMS> "
            + "</SOAP-ENV:Body> "
            + "</SOAP-ENV:Envelope>";
    static final String SOAP_BODY_TEMPLATE_EMAIL = "<SOAP-ENV:Body> "
            + "<n2:SendMail xmlns:n2=\"http://tempuri.org/\"> "
            + "<n2:mail xmlns:n3=\"http://schemas.datacontract.org/2004/07/Tencent.OA.Framework.Messages.DataContract\"> "
            + "<n3:Attachments>{0}</n3:Attachments> "
            + "<n3:Bcc>{1}</n3:Bcc> "
            + "<n3:BodyFormat>{2}</n3:BodyFormat> "
            + "<n3:CC>{3}</n3:CC> "
            + "<n3:Content><![CDATA[{4}]]></n3:Content> "
            + "<n3:EmailType>{5}</n3:EmailType> "
            + "<n3:From>{6}</n3:From> "
            + "<n3:Location xsi:nil=\"true\"></n3:Location> "
            + "<n3:Organizer xsi:nil=\"true\"></n3:Organizer> "
            + "<n3:Priority>{7}</n3:Priority> "
            + "<n3:Title><![CDATA[{8}]]></n3:Title> "
            + "<n3:To>{9}</n3:To> "
            + "</n2:mail> "
            + "</n2:SendMail> "
            + "</SOAP-ENV:Body> "
            + "</SOAP-ENV:Envelope>";
    static final String SOAP_BODY_TEMPLATE_EMAIL_ATTACH = "<n3:TencentMailAttachment xmlns=\"http://schemas.microsoft.com/2003/10/Serialization/\" >"
            + "<n3:FileContent>{0}</n3:FileContent>"
            + "<n3:FileName>{1}</n3:FileName>"
            + "</n3:TencentMailAttachment>";

    private MessageServiceProxy() {
    }

    public static MessageServiceProxy getInstance() {
        return instance;
    }

    private String getMessageBody4RTX(String sender, String receiver, String title, String msgInfo, String priority) {
        MessageFormat format = new MessageFormat(SOAP_BODY_TEMPLATE_RTX);
        return format.format(new String[]{msgInfo, priority, receiver, sender, title});
    }

    private String getMessageBody4SMS(String sender, String receiver, String msgInfo, String priority) {
        MessageFormat format = new MessageFormat(SOAP_BODY_TEMPLATE_SMS);
        return format.format(new String[]{msgInfo, priority, receiver, sender});
    }

    private String getMessageBodyEmail(String from, String to, String cc, String bcc, String title, String content, String priority, String bodyFormat, String emailType, String attach) {
        MessageFormat format = new MessageFormat(SOAP_BODY_TEMPLATE_EMAIL);
        return format.format(new String[]{attach, bcc, bodyFormat, cc, content, emailType, from, priority, title, to});
    }

    private String getMessageBodyEmailAttach(String fileName, String base64String) {
        MessageFormat format = new MessageFormat(SOAP_BODY_TEMPLATE_EMAIL_ATTACH);
        return format.format(new String[]{base64String, fileName});
    }

    public String sendRTX(String sender, String receiver, String title, String msgInfo, String priority) {
        if (!validateParamsNotEmpty(new String[]{receiver, msgInfo})) {
            logger.warn("Send RTX failure, some key field value is null or empty, Receiver=" + receiver + ":MsgInfo=" + msgInfo);
            return "false";
        }
        if (sender == null) {
            sender = "";
        }
        if (title == null) {
            title = "";
        }
        priority = validatePriority(priority);
        String soapxml = SOAP_HEADER + getMessageBody4RTX(sender, receiver, title, msgInfo, priority);
        return sendSoapToWebService(soapxml, MessageServiceProxy.SEND_TYPE_RTX);
    }

    public String sendSMS(String sender, String receiver, String msgInfo, String priority) {
        if (!validateParamsNotEmpty(new String[]{receiver, msgInfo})) {
            logger.warn("Send SMS refused, some key field value is null or empty, Receiver=" + receiver + ":MsgInfo=" + msgInfo);
            return "false";
        }
        if (sender == null) {
            sender = "";
        }
        priority = validatePriority(priority);
        String soapxml = SOAP_HEADER + getMessageBody4SMS(sender, receiver, msgInfo, priority);
        return sendSoapToWebService(soapxml, MessageServiceProxy.SEND_TYPE_SMS);
    }

    public String sendMail(String from, String to, String cc, String bcc, String title, String content, String priority, String bodyFormat, String emailType, List<String> attachFilePath) {
        if (!validateParamsNotEmpty(new String[]{from, to, content})) {
            logger.warn("Send Email refuse, some key field value is null or empty, from=" + from + ":to=" + to);
            return "false:some key feilds value is null.";
        }
        if (title == null) {
            title = "";
        }
        if (cc == null) {
            cc = "";
        }
        if (bcc == null) {
            bcc = "";
        }
        bodyFormat = validateMailBodyFormat(bodyFormat);
        emailType = validateMailType(emailType);
        priority = validatePriority(priority);
        String soapxml = SOAP_HEADER + getMessageBodyEmail(from, to, cc, bcc, title, content, priority, bodyFormat, emailType, getAttachFile2String(attachFilePath));
        return sendSoapToWebService(soapxml, MessageServiceProxy.SEND_TYPE_EMAIL);
    }

    private String validatePriority(String priority) {
        if (priority == null || !(MSG_PRIORITY_HIGHT.equals(priority) || MSG_PRIORITY_NORMAL.equals(priority) || MSG_PRIORITY_LOW.equals(priority))) {
            priority = MessageServiceProxy.MSG_PRIORITY_LOW;
        }
        return priority;
    }

    private String validateMailBodyFormat(String bodyFormat) {
        if (bodyFormat == null || !(MSG_MAIL_BODYFORMAT_HTML.equals(bodyFormat)
                || MSG_MAIL_BODYFORMAT_TEXT.equals(bodyFormat))) {
            bodyFormat = MessageServiceProxy.MSG_MAIL_BODYFORMAT_HTML;
        }
        return bodyFormat;
    }

    private String validateMailType(String emailType) {
        if (emailType == null || !(MSG_MAIL_TYPE_INTERNET.equals(emailType)
                || MSG_MAIL_TYPE_ENCHANGE.equals(emailType)
                || MSG_MAIL_TYPE_MEETING.equals(emailType))) {
            emailType = MessageServiceProxy.MSG_MAIL_TYPE_INTERNET;
        }
        return emailType;
    }

    private boolean validateParamsNotEmpty(String... params) {
        for (String p : params) {
            if (p == null || "".equals(p.trim())) {
                return false;
            }
        }
        return true;
    }

    private String sendSoapToWebService(String soapSMSXml, String sendType) {
        if (soapSMSXml == null) {
            return ("false:Soap is null!");
        }
        try {
            URL url = new URL("http://ws.tof.oa.com/MessageService.svc");
            HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
            httpUrlConn.setRequestMethod("POST");
            httpUrlConn.setDoInput(true);
            httpUrlConn.setDoOutput(true);
            httpUrlConn.setRequestProperty("Content-Type", " text/xml; charset=UTF-8");
            httpUrlConn.setRequestProperty("Content-Length", Integer.toString(soapSMSXml.length()));
            httpUrlConn.setRequestProperty("SOAPAction", "\"http://tempuri.org/IMessageService/" + sendType + "\"");

            OutputStream os = httpUrlConn.getOutputStream();
            OutputStreamWriter osw = new OutputStreamWriter(os, "utf-8");
            osw.write(soapSMSXml);
            osw.flush();
            osw.close();
            String msg = httpUrlConn.getResponseMessage();
            httpUrlConn.disconnect();
            return msg;
        } catch (Exception e) {
            logger.error("sendSoapToWebService error", e);
            return "false:" + e.getMessage();
        }
    }

    private String getAttachFile2String(List<String> fileList) {
        if (fileList == null) {
            return "";
        }
        StringBuffer attachStr = new StringBuffer("");
        for (String filePath : fileList) {
            File f = new File(filePath);
            if (f.exists()) {
                try {
                    String base64 = getBase64Encoder(filePath);
                    String oneFileStr = getMessageBodyEmailAttach(f.getName(), base64);
                    attachStr.append(oneFileStr);
                } catch (Exception e) {
                    logger.warn("Read Attach File Error", e);
                }
            } else {
                logger.info("Attach file " + filePath + " is not exist.");
            }
        }
        return attachStr.toString();
    }

    private String getBase64Encoder(String filePath) throws Exception {
        String ret = "";
        InputStream in = null;
        try {
            File f = new File(filePath);
            byte buff[] = new byte[(int) f.length()];
            in = new FileInputStream(f);
            in.read(buff);            
            byte[] encoded = Base64.encodeBase64(buff);
            ret = new String(encoded);
        } catch (Exception e) {
            logger.error("getBase64Encoder Error", e);
            throw e;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    logger.warn("getBase64Encoder close input stream error", e);
                }
            }
        }
        return ret;
    }
}
